﻿// ***********************************************************************
// Assembly         : GooglePredict
// Author           : aj
// Created          : 10-08-2010
//
// Last Modified By : aj
// Last Modified On : 10-08-2010
// Description      : 
//
//
// ***********************************************************************
namespace Google.API.Predict
{
    using System.Reflection;
    using System;

    /// <summary>
    /// Source code taken from: (These lines of code made this project possible, seriously.)
    /// http://grootveld.com/archives/21/url-encoded-slashes-in-systemuri
    /// </summary>
    static class UriHacks
    {
        /// <summary>
        /// System.UriSyntaxFlags is internal, so let's duplicate the flag privately
        /// </summary> 
        private const int UnEscapeDotsAndSlashes = 0x2000000;

        /// <summary>
        /// Came with LeaveMultipleSlashesAsIs
        /// </summary>
        private const int CompressPath = 0x800000;

        /// <summary>
        /// Fixes uris that need escaped slashes
        /// Such as: bucket%2Fdata
        /// </summary>
        /// <param name="uri">Uri to fix</param>
        public static void LeaveDotsAndSlashesEscaped(this Uri uri)
        {
            if (uri == null)
            {
                throw new ArgumentNullException("uri");
            }

            var fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic);
            if (fieldInfo == null)
            {
                throw new MissingFieldException("'m_Syntax' field not found");
            }

            var uriParser = fieldInfo.GetValue(uri);

            fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
            if (fieldInfo == null)
            {
                throw new MissingFieldException("'m_Flags' field not found");
            }

            var uriSyntaxFlags = fieldInfo.GetValue(uriParser);

            // Clear the flag that we don't want
            uriSyntaxFlags = (int)uriSyntaxFlags & ~UnEscapeDotsAndSlashes;

            fieldInfo.SetValue(uriParser, uriSyntaxFlags);
        }

        /// <summary>
        /// Threw this in here just in case
        /// </summary>
        /// <param name="uri">Uri to apply the hack to :)</param>
        public static void LeaveMultipleSlashesAsIs(Uri uri)
        {
            if (uri == null)
            {
                throw new ArgumentNullException("uri");
            }

            var fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic);
            if (fieldInfo == null)
            {
                throw new MissingFieldException("'m_Syntax' field not found");
            }

            var uriParser = fieldInfo.GetValue(uri);

            fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
            if (fieldInfo == null)
            {
                throw new MissingFieldException("'m_Flags' field not found");
            }

            var uriSyntaxFlags = fieldInfo.GetValue(uriParser);

            // Clear the flag that we don't want
            uriSyntaxFlags = (int)uriSyntaxFlags & ~CompressPath;

            fieldInfo.SetValue(uriParser, uriSyntaxFlags);
        }
    }
}
